package gadgetwars.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import gadgetwars.server.SignedRequestsHelper;
import gadgetwars.shared.AmazonData;
import gadgetwars.shared.YahooImage;

import gadgetwars.server.GadgetInfo;
import gadgetwars.server.PMF;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import gadgetwars.client.GadgetWarsService;
import gadgetwars.shared.DiggNews;

public class GadgetWarsServiceImpl extends RemoteServiceServlet implements GadgetWarsService{
	private static final long serialVersionUID = 1L;
	private String sort = "digg_count-desc";
	public DiggNews[] getDiggNews(String gadget, String sortOrder,int gadgetIndex){
			try{
				final String apiUrl = "http://services.digg.com/2.0/search.search";

				//String query = "?sort=" + sortOrder + "&query=" + gadget;
				String query = "?count=10&sort=" + sort + "&query=" + gadget;
				String diggUrl = apiUrl + query;
				String json = getJSONData(diggUrl);
				JSONArray diggNewsResult = new JSONObject(json).getJSONArray("stories");
				DiggNews[] diggNewsArray = new DiggNews[diggNewsResult.length()];
				//System.out.println("Digg news size:" + diggNewsResult.length());
				for(int i=0; i<diggNewsResult.length(); i++){
					JSONObject diggNews = diggNewsResult.getJSONObject(i);
					int diggs = diggNews.getInt("diggs");
					String title = diggNews.getString("title");
					Date date = new Date((long)diggNews.getInt("submit_date")*1000);
					String image = diggNews.getJSONObject("thumbnail").getString("src");
					String url = diggNews.getString("link");
					String description = diggNews.getString("description");
					diggNewsArray[i] = new DiggNews(diggs, title, date, image, url, description);
				}
				return diggNewsArray;								
			}catch(JSONException e){
				e.printStackTrace();
			}
			return null;
		}
	
	private String getJSONData(String apiUrl) {
		StringBuilder json = new StringBuilder();
		try{
			URL url = new URL(apiUrl.replaceAll(" ", "%20"));
			URLConnection urlc = url.openConnection();
	        BufferedReader in = new BufferedReader(
	                                new InputStreamReader(
	                                urlc.getInputStream()));
	        String inputLine;
	        while ((inputLine = in.readLine()) != null){ 
	            json.append(inputLine.trim());
	        }
	        in.close();
		}catch(MalformedURLException e){
			e.printStackTrace();
		}catch(IOException e){
			e.printStackTrace();
		}
		return json.toString();
	}
	
	public AmazonData getAmazonData(String gadget, int gadgetIndex) {
		String ITEM_ID = getGadgetInfo(gadget).getAmazonId();
		//String ITEM_ID ="B0041E16RC";
		try{
			final String AWS_ACCESS_KEY_ID = "AKIAJTMWGB73ZXRSV4SA";
		   	final String AWS_SECRET_KEY = "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";
	    	final String ENDPOINT = "ecs.amazonaws.com";
	 		
	        SignedRequestsHelper helper;
	        
	    	helper = SignedRequestsHelper.getInstance(ENDPOINT, AWS_ACCESS_KEY_ID, AWS_SECRET_KEY);
			
	        String requestUrl = null;
	
	
	        Map<String, String> params = new HashMap<String, String>();
	        params.put("Service", "AWSECommerceService");
	        params.put("Version", "2010-11-01");
	        params.put("Operation", "ItemLookup");
	        params.put("ItemId", ITEM_ID);
	        params.put("ResponseGroup", "Small,OfferFull,Similarities,Reviews,EditorialReview");
	
	        requestUrl = helper.sign(params);
	        
	    	String itemTitle = null;
	    	String itemAsin = null;
	        String itemLowestNewPrice = null;
	        String itemLowestUsedPrice = null;
	    	String itemLowestCollectiblePrice = null;
	    	String itemMerchantId = null;
	    	String itemMerchantName = null;
	    	String itemMerchantGlancePage = null;
	    	String itemIFrameURL = null;
	    	String itemPageURL = null;
	    	String itemeditorialReview = null;
	
		    String[] itemSimilarityASIN = new String[5];
		    String[] itemSimilarityTitle = new String[5];
	
	            
	        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
	        DocumentBuilder db = dbf.newDocumentBuilder();
	        Document doc = db.parse(requestUrl);
	        
	
	        /* Extracting the title of the Item */
	        Node titleNode = doc.getElementsByTagName("Title").item(0);
	        itemTitle = titleNode.getTextContent();
	
	        /* Extracting the Amazon Item Number of the Item */
	        Node asinNode = doc.getElementsByTagName("ASIN").item(0);
	        itemAsin = asinNode.getTextContent();
	
	        /* Extracting the Amazon Detailed page URL of the Item */
	        Node pageURLNode = doc.getElementsByTagName("DetailPageURL").item(0);
	        itemPageURL = pageURLNode.getTextContent();
	
	        /* Extracting the Amazon Editorial Review of the Item */
	        Node eReviewNode = doc.getElementsByTagName("Content").item(0);
	        itemeditorialReview = eReviewNode.getTextContent();
	
	        /* Extracting the customer review URL of the Item */
	        Node iFrameURLNode = doc.getElementsByTagName("IFrameURL").item(0); // Not found
	        itemIFrameURL = iFrameURLNode.getTextContent();  
	
	        /* Extracting the Lowest New Price of the Item */
	        Node newPriceNode = doc.getElementsByTagName("FormattedPrice").item(0);
	        itemLowestNewPrice = newPriceNode.getTextContent();  
	
	        /* Extracting the Lowest Used Price of the Item */
	        NodeList nodeLst = doc.getElementsByTagName("LowestUsedPrice");
	        for (int s = 0; s < nodeLst.getLength(); s++) {
	          Node fstNode = nodeLst.item(s);       
	          if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
	            Element fstElmnt = (Element) fstNode;
	            NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("FormattedPrice");
	            Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
	            NodeList fstNm = fstNmElmnt.getChildNodes();
	            itemLowestUsedPrice = ((Node) fstNm.item(0)).getNodeValue();
	          }
	        }
	        
	        /* Extracting the Lowest Collectible Price of the Item */
	        NodeList lcpnodeLst = doc.getElementsByTagName("LowestCollectiblePrice");//not found
	        for (int s = 0; s < lcpnodeLst.getLength(); s++) {
	          Node fstNode = lcpnodeLst.item(s);       
	          if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
	            Element fstElmnt = (Element) fstNode;
	            NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("FormattedPrice");
	            Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
	            NodeList fstNm = fstNmElmnt.getChildNodes();
	            itemLowestCollectiblePrice = ((Node) fstNm.item(0)).getNodeValue();
	          }
	        }
	        
	        /* Extracting the Merchant Details of the Item's new price  */
	        NodeList mnodeLst = doc.getElementsByTagName("Merchant");
	        for (int s = 0; s < mnodeLst.getLength(); s++) {
	          Node fstNode = mnodeLst.item(s);       
	          if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
	            Element fstElmnt = (Element) fstNode;
	            NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("MerchantId");
	            Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
	            NodeList fstNm = fstNmElmnt.getChildNodes();
	            itemMerchantId = ((Node) fstNm.item(0)).getNodeValue();
	
	            NodeList secNmElmntLst = fstElmnt.getElementsByTagName("Name");
	            Element secNmElmnt = (Element) secNmElmntLst.item(0);
	            NodeList secNm = secNmElmnt.getChildNodes();
	            itemMerchantName = ((Node) secNm.item(0)).getNodeValue();
	
	            NodeList trdNmElmntLst = fstElmnt.getElementsByTagName("GlancePage");
	            Element trdNmElmnt = (Element) trdNmElmntLst.item(0);
	            NodeList trdNm = trdNmElmnt.getChildNodes();
	            itemMerchantGlancePage= ((Node) trdNm.item(0)).getNodeValue();
	          }
	        }
	        
	        /* Extracting the Similar products details of the Item  */
	        NodeList snodeLst = doc.getElementsByTagName("SimilarProduct");
	        for (int s = 0; s < snodeLst.getLength(); s++) {
	          Node fstNode = snodeLst.item(s);       
	          if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
	            Element fstElmnt = (Element) fstNode;
	            
	            NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("ASIN");
	            Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
	            NodeList fstNm = fstNmElmnt.getChildNodes();
	            itemSimilarityASIN[s] = ((Node) fstNm.item(0)).getNodeValue();
	
	            NodeList secNmElmntLst = fstElmnt.getElementsByTagName("Title");
	            Element secNmElmnt = (Element) secNmElmntLst.item(0);
	            NodeList secNm = secNmElmnt.getChildNodes();
	            itemSimilarityTitle[s] = ((Node) secNm.item(0)).getNodeValue();
	          }
	        }
	        
	        AmazonData amazonData = new AmazonData(	itemTitle,
													itemAsin,
													itemLowestNewPrice,
													itemLowestUsedPrice,
												    itemLowestCollectiblePrice,
													itemMerchantId,
													itemMerchantName,
													itemMerchantGlancePage,
													itemIFrameURL,
													itemPageURL,
													itemeditorialReview,
													itemSimilarityASIN,
													itemSimilarityTitle
													) ;
	        //amazonData.printAmazonData();
	        return amazonData;
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
        
    }
	
	public YahooImage getYahooImage(String gadget, int gadgetIndex) {
		
		String requestUrl = "http://search.yahooapis.com/ImageSearchService/V1/imageSearch?appid=SPGDGAjV34HZNQ3im5lj30oh5HEYy8H1Cs.xTyrrZ1o6tMWFw3uRviBVMnvYYvRZkSvyZPvsRCxBW98ibRLJg9TK4MfZSTg-&results=10&query="+gadget;
	   	String[] imageTitle = new String[10];
    	String[] imageSummary = new String[10];
    	String[] imageUrl = new String[10];
    	String[] imageClickUrl = new String[10];
    	String[] imageRefererUrl = new String[10];
    	String[] imageFileSize = new String[10];
    	String[] imageFileFormat = new String[10];
    	String[] imageHeight = new String[10];
    	String[] imageWidth = new String[10];
    	String[] thumbnailWidth = new String[10];
    	String[] thumbnailHeight = new String[10];
    	String[] thumbnailUrl = new String[10];
        
        
		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document doc = db.parse(requestUrl);

	    	NodeList titleNodes = doc.getElementsByTagName("Title");
	    	NodeList summaryNodes = doc.getElementsByTagName("Summary");
	    	NodeList urlNodes = doc.getElementsByTagName("Url");
	    	NodeList clickUrlNodes = doc.getElementsByTagName("ClickUrl");
	    	NodeList refererNodes = doc.getElementsByTagName("RefererUrl");
	    	NodeList fileSizeNodes = doc.getElementsByTagName("FileSize");
	    	NodeList fileFormatNodes = doc.getElementsByTagName("FileFormat");
	    	NodeList heightNodes = doc.getElementsByTagName("Height");
	    	NodeList widthNodes = doc.getElementsByTagName("Width");
	     	
	    	for(int i=0;i<10;i++){
	        imageTitle[i] = titleNodes.item(i).getTextContent();
	        imageSummary[i] = summaryNodes.item(i).getTextContent();
	        
	        imageUrl[i] = urlNodes.item(i*2).getTextContent();
	        thumbnailUrl[i] = urlNodes.item(i*2+1).getTextContent();
	        
	        imageClickUrl[i] = clickUrlNodes.item(i).getTextContent();
	        imageRefererUrl[i] = refererNodes.item(i).getTextContent();
	        imageFileSize[i] = fileSizeNodes.item(i).getTextContent();
	        imageFileFormat[i] = fileFormatNodes.item(i).getTextContent();
	        imageHeight[i] = heightNodes.item(i*2).getTextContent();
	        thumbnailHeight[i] = heightNodes.item(i*2+1).getTextContent();
	        imageWidth[i] = widthNodes.item(i*2).getTextContent();
	        thumbnailWidth[i] = widthNodes.item(i*2+1).getTextContent();
			
	    	}
	    	
	    	YahooImage yahooImage = new YahooImage(imageTitle,
		    			imageSummary,
		    			imageUrl,
		    			imageClickUrl,
		    			imageRefererUrl,
		    			imageFileSize,
		    			imageFileFormat,
		    			imageHeight, 			
		    			imageWidth,
		    			thumbnailWidth,
		    			thumbnailHeight,
		    			thumbnailUrl);
			return yahooImage;
			
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;			
    	}
	
	
	public Boolean insertInitialData() {
        GadgetInfo[] initialGadgets = new GadgetInfo[22];
        initialGadgets[0] = new GadgetInfo("HTC Droid Incredible", "B003KKH5OG");
        initialGadgets[1] = new GadgetInfo("Apple iPhone 4", "B0041E16RC");
        initialGadgets[2] = new GadgetInfo("HTC Nexus One", "B00332YPHQ");
        initialGadgets[3] = new GadgetInfo("HTC Evo", "B004KFXTOA");
        initialGadgets[4] = new GadgetInfo("Samsung Focus", "B004H23JXW");
        initialGadgets[5] = new GadgetInfo("Kodak Z18", "B002HOPUPC");
        initialGadgets[6] = new GadgetInfo("Samsung HMX-U10", "B00365F6EQ");
        initialGadgets[7] = new GadgetInfo("Microsoft XBox 360", "B000KA5T6A");
        initialGadgets[8] = new GadgetInfo("Sony Playstation 3", "B003VUO6H4");
        initialGadgets[9] = new GadgetInfo("Nintendo Wii", "B0045F8QDE");
        initialGadgets[10] = new GadgetInfo("Amazon Kindle", "B002Y27P3M");
        initialGadgets[11] = new GadgetInfo("Barnes & Noble Nook", "1400532620");
        initialGadgets[12] = new GadgetInfo("Apple iPad", "B002C7481G");
        initialGadgets[13] = new GadgetInfo("Samsung Galaxy Tab", "B00480P67K");
        initialGadgets[14] = new GadgetInfo("Microsoft Kinect", "B002BSA298");
        initialGadgets[15] = new GadgetInfo("Sony Playstation Move", "B002I0K956");
        initialGadgets[16] = new GadgetInfo("Apple Macbook Pro", "B002QQ8H8I");
        initialGadgets[17] = new GadgetInfo("Toshiba Portege", "B0041O425K");
        initialGadgets[18] = new GadgetInfo("Flip UltraHD", "B0040702HA");         
        initialGadgets[19] = new GadgetInfo("Motorola Xoom", "B004P4HFX2");
        initialGadgets[20] = new GadgetInfo("HTC Surround", "B004FGCYQS");//
        initialGadgets[21] = new GadgetInfo("LG Quantum", "B0047T74VI");//
        
        

        PersistenceManager pm = PMF.get().getPersistenceManager();
        	
			try{
				for(int j=0;j<initialGadgets.length;j++){
					GadgetInfo gadgetInfo;
					Query query = pm.newQuery(GadgetInfo.class);
					query.setFilter("gadgetName == gadgetNameParam");
					query.declareParameters("String gadgetNameParam");				
					List<GadgetInfo> gadgetInfoList = (List<GadgetInfo>)query.execute(initialGadgets[j].getGadgetName());
					System.out.println("Size:" + gadgetInfoList.size());
					for(int i=0;i<gadgetInfoList.size();i++) {
						gadgetInfo = gadgetInfoList.get(i);
						pm.deletePersistent(gadgetInfo);				
					}
				}	
		        for(int i=0; i< initialGadgets.length-1; i++){
		                pm.makePersistent(initialGadgets[i]);      
		        }
		        System.out.println("Finish Insert.");		        	
		} finally {
		    pm.close();
		}
		return new Boolean(true);
}
	@SuppressWarnings("unchecked")
	public String[] getGadgetNames(){
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try{
			Query query = pm.newQuery(GadgetInfo.class);
			List<GadgetInfo> gadgetInfoList = (List<GadgetInfo>)query.execute();
			String[] gadgetNames = new String[gadgetInfoList.size()];
			for(int i=0; i<gadgetInfoList.size(); i++){
				gadgetNames[i] = gadgetInfoList.get(i).getGadgetName();
				System.out.println(gadgetNames[i]);
			}
			return gadgetNames;
		}finally{
			pm.close();
		}
	}
	
	@SuppressWarnings("unchecked")
	private GadgetInfo getGadgetInfo(String gadgetName){
		PersistenceManager pm = PMF.get().getPersistenceManager();
		GadgetInfo gadgetInfo;
		try{
			Query query = pm.newQuery(GadgetInfo.class);
			query.setFilter("gadgetName == gadgetNameParam");
			query.declareParameters("String gadgetNameParam");
			List<GadgetInfo> gadgetInfoList = (List<GadgetInfo>)query.execute(gadgetName);
			System.out.println("Size:" + gadgetInfoList.size());
			for(int i=0;i<gadgetInfoList.size();i++) System.out.println(gadgetInfoList.get(i).getGadgetName());
			if(gadgetInfoList.size() != 1){
				System.err.println("No or more than one value returned");
				gadgetInfo = null;
				//gadgetInfo = gadgetInfoList.get(gadgetInfoList.size()-1);
			}else{
				gadgetInfo = gadgetInfoList.get(0);
			}
		}finally{
			pm.close();
		}
		return gadgetInfo;
	}
        
			
}
